import re

# match(): 匹配字符串开头
match = re.match(r"\d+", "12345abc")
print("match.group():", match.group())  # match.group(): 12345

print("=" * 50)
# search(): 在整个字符串中搜索第一匹配正则表达式模式的子串
search = re.search(r"\d+", "abc12345")
print("search.group():", search.group())    # search.group(): 12345

print("=" * 50)
# findall(): 搜索字符串，返回所有匹配的字符串列给
findall = re.findall(r"\d+", "abc12345cd23h789")
print("findall:", findall)  # findall: ['12345', '23', '789']

print("=" * 50)
# finditer(): 搜索字符串，返回所有匹配的迭代器对象
finditer = re.finditer(r"\d+", "abc12345cd23h789")
for match in finditer:
    print("match.group():", match.group())

# sub(): 替换字符串中所有匹配正则表达式模式的子串，返回匹配后的结果
sub = re.sub(r"\d+", "0", "abc12345cd23h789")
print("sub:", sub)  # sub: abc0cd0h0

print("=" * 50)
# 正则表达式语法
# 字符匹配
# . 表示匹配任意一个字符，除了换行符
# ^ 表示匹配字符串开头
# $ 匹配字符串结尾
print(re.match(r'a.b', 'a&b').group())  # a&b
print(re.match(r'^Hello', 'Hello World').group())   # Hello
print(re.match(r'.*World$', 'Hello World').group()) # Hello World
print(re.search(r'^Hello', 'Hello Hello World').group())  # Hello
print(re.search(r'World$', 'Hello Hello World').group())    # World

print("=" * 50)
# 字符集
# [abc] 表示匹配a、b、c中的任意一个字符
print(re.match(r'[abc]', 'a').group())  # a
# [^abc] 表示匹配除了a、b、c之外的任意一个字符
print(re.match(r'[^abc]', 'd').group()) # d
# [a-z] 匹配a到z之间的任意一个字符
print(re.match(r'[a-z]', 'a').group())  # a
# [0-9] 匹配0到9之间的任意一个字符
print(re.match(r'[0-9]', '3').group())  # 3

print("=" * 50)
# 量词
# * 匹配0个或多个字符
print(re.match(r'a*b', 'aaaab').group())    # aaaab
# + 匹配1个或多个字符
print(re.match(r'a+b', 'aaaab').group())    # aaaab
# ? 匹配0个或1个字符
print(re.match(r'a?b', 'b').group())        # b
# {n} 匹配n个字符
print(re.match(r'a{2}b', 'aab').group())    # aab
# {n,m} 匹配最少n次最多m次
print(re.match(r'a{2,3}b', 'aaab').group()) # aaab

print("=" * 50)
# 分组捕获
# (): 创建一个分组，并返回匹配的子串
print(re.match(r'([a-z]+)([0-9]+)', 'abc123').group())  # abc123
print(re.match(r'([a-z]+)([0-9]+)', 'abc123').group(1)) # abc
print(re.match(r'([a-z]+)([0-9]+)', 'abc123').group(2)) # 123
# (?:): 创建一个分组，但不返回匹配的子串
print(re.match(r'(?:[a-z]+)([0-9]+)', 'abc123').group())    # abc123
# (?:[a-z])是非捕获组，不计入分组编号，所以后面的([0-9]+)会记到第1个捕获组
print(re.match(r'(?:[a-z]+)([0-9]+)', 'abc123').group(1))   # 123

print("=" * 50)
# 特殊字符和转义
# \d 表示匹配数字
print(re.match(r'\d+', '345abc').group())   # 345
# \D 匹配非数字
print(re.match(r'\D+', 'abc').group())  # abc
# \w 匹配字母、数字、下划线
print(re.match(r'\w+', 'Aabc_123#@').group())   # Aabc_123
# \W 匹配非字母、数字、下划线
print(re.match(r'\W+', '##￥Aabc_123#@').group())    # ##￥
# \s 匹配空白字符，包括空格、制表符、换行符
print(re.match(r'\s+', '   abc').group())   #
# \S 匹配非空白字符
print(re.match(r'\S+', 'abc').group())  # abc
# \b 匹配单词边界
print(re.match(r'\bword\b', 'word boundary').group())   #  word
# \B 匹配非单词边界
# 这里\B匹配的是非单词边界，由于wording中d的后面是i不是单词边界，所以匹配成功word
print(re.match(r'word\B', 'wording').group())   # word
